package model;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

/**
 * A simple model of a rabbit.
 * Rabbits age, move, breed, and die.
 * 
 * @author David J. Barnes and Michael Kölling
 * @version 2011.07.31
 */
public class Rabbit extends Animal
{
    // Characteristics shared by all rabbits (class variables).

    // The age at which a rabbit can start to breed.
    private static int BREEDING_AGE = 4;
    // The age to which a rabbit can live.
    private static int MAX_AGE = 40;
    // The likelihood of a rabbit breeding.
    private static double BREEDING_PROBABILITY = 0.2;
    // The maximum number of births.
    private static int MAX_LITTER_SIZE = 4;    
    // The age at which a rabbit can start to breed.
    private static final int GRASS_FOOD_VALUE = 3;
    // A shared random number generator to control breeding.
    private static final Random rand = Randomizer.getRandom();
    
    // Individual characteristics (instance fields).
    private boolean canGetSick;
    private static double diseasePercentage = 0.9;
    
    public Rabbit(){}

    /**
     * Create a new rabbit. A rabbit may be created with age
     * zero (a new born) or with a random age.
     * 
     * @param randomAge If true, the rabbit will have a random age.
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
    public Rabbit(boolean randomAge, Field field, Location location)
    {
        super(field, location);
        setAge(0);
        foodLevel = 4;
        if(randomAge) {
            setAge(rand.nextInt(MAX_AGE));      
        }
        if(rand.nextDouble() < diseasePercentage){
        	canGetSick = true;
        } else {
        	canGetSick = false;
        }
        if(canGetSick == true && (rand.nextDouble() < 0.01)){
        	setSick(true);
        }
        
    }
    
    /**
     * 
     * @param randomAge
     * @param field
     * @param location
     * @param canGetSick
     */
    public Rabbit(int age, Field field, Location location, boolean canGetSick)
    {
        super(field, location);
        setAge(0);
        foodLevel = 4;
        setAge(age);
        this.canGetSick = canGetSick;
        
    }
    
    public boolean canGetSick() {
    	return canGetSick;
    }
    
    /**
     * This is what the rabbit does most of the time - it runs 
     * around. Sometimes it will breed or die of old age.
     * @param newRabbits A list to return newly born rabbits.
     */
    public void act(List<Actor> newAnimals) {
    	super.act(newAnimals);
        if(isAlive()) { 
            giveBirth(newAnimals);
            advanceDisease();
        }
    }
    
    /**
     * Look for food adjacent to the current location.
     * Only the first grass is eaten.
     * @return Where food was found, or null if it wasn't.
     */
    protected Location findFood() {
        Field field = getField();
        List<Location> adjacent = field.adjacentLocations(getLocation());
        Iterator<Location> it = adjacent.iterator();
        while(it.hasNext()) {
            Location where = it.next();
            Object animal = field.getObjectAt(where);
            if(animal == null) {
            	Object modifier = field.getModifierAt(where);
            	if(modifier instanceof ModifierGrass) {
            		ModifierGrass grass = (ModifierGrass) modifier;
            		if(grass.isEdible()) {
            			grass.setAge(0);
            			foodLevel = GRASS_FOOD_VALUE;
            			return where;
            		}
                }
            }
        }
        return null;
    }
    
    /**
     * 
     */
    private void advanceDisease() {
    	if(getSick()){
    		List<Location> locations = getField().adjacentLocations(getLocation());
    		for(Location location : locations) {
    			Object o = getField().getObjectAt(location);
    			if(o instanceof Rabbit) {
    				Rabbit rabbit = (Rabbit) o;
    				if(rabbit.canGetSick) {
    					Diseases.infect(rabbit);
    				}
    			}
    		}
    		if(getSickCounter() < 5) {
    			incrementSickCounter();
    		} else {
    			setDead();
    		}
    	}
    }
    
	@Override
	public boolean isActive() {
		return true;
	}

	@Override
	public int getMaxAge() {
		return MAX_AGE;
	}

	@Override
	public int getBreedingAge() {
		return BREEDING_AGE;
	}

	@Override
	public double getBreedingProbability() {
		return BREEDING_PROBABILITY;
	}

	@Override
	public int getMaxLitterSize() {
		return MAX_LITTER_SIZE;
	}
	
	@Override
	public Animal newYoung(Location location) {
		return new Rabbit(false, getField(), location);
	}

	@Override
	public void setMaxAge(int maxAge) {
		Rabbit.MAX_AGE = maxAge;
	}

	@Override
	public void setBreedingAge(int breedingAge) {
		Rabbit.BREEDING_AGE = breedingAge;
	}

	@Override
	public void setBreedingProbability(double breedingProbability) {
		Rabbit.BREEDING_PROBABILITY = breedingProbability;
		
	}

	@Override
	public void setMaxLitterSize(int maxLitterSize) {
		Rabbit.MAX_LITTER_SIZE = maxLitterSize;
	}
	
	public String toString() {
		return "Rabbit";
	}

	public static double getDiseasePercentage() {
		return diseasePercentage;
	}

	public static void setDiseasePercentage(double diseasePercentage) {
		Rabbit.diseasePercentage = diseasePercentage;
	}
}
